#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <work.h>
#include <crc16.h>
#include <errmessage.h>
#include <stringFun.h>
#include <dataStore.h>

/*
*	函数功能：		更新节点上报时间
*	函数参数	：	节点指针
*	函数返回值：是否更新成功
*				成功：0
*				失败：<0
*/
static int updateNodeTime(PT_nodeList me)
{
	int ret;
	
	ret = nodeList_updateTime(me);
	if(ret <0)
	{
		syslog(LOG_ERR,"Analysis editNode updateTime error");
		err_message(me->client_fd, UPDATERIME_ERR);
		return ret;
	}

	return 0;
}

/*
*	函数功能：		crc16校验
*	函数参数	：	1、客户端
*				2、数据地址
*				3、数据长度包含CRC
*	函数返回值：校验是否成功
*				成功：0
*				失败：<0
*/
static int crc16Check(int clientfd, void *buff, int lenth)
{
	int crc16_data=0;
	
	crc16_data = CRC16((char *)buff,lenth-2);
	if(((crc16_data&0xff) != ((((char*)buff)[lenth-2])&0xff)) || (((crc16_data>>8)&0xff) != ((((char*)buff)[lenth-1])&0xff)))
	{
		syslog(LOG_ERR,"crcCheck error");
		err_message(clientfd, CRC_ERR);
		return -1;
	}

	return 0;
}

/*
*	函数功能：		数据处理
*	函数参数	：	待处理节点指针
*	函数返回值：是否处理成功
*				成功：0
*				失败：<0
*/
static int dataProcessing(PT_nodeList me)
{
	int ret;
	int copyLenth;
	struct data_st *ptr;

	if(me==NULL || me->recvDataBuff ==NULL)
	{
		syslog(LOG_ERR,"dataProcessing params error");
		err_message(me->client_fd, PARAMAS_ERR);
		return -1;
	}

	ptr = me->recvDataBuff;
	//满足一包数据长度处理数据
	if(me->recvDataLenth >= ptr->datalenth+6)
	{
		//判断数据长度是否超过定义的结构体长度
		if(ptr->datalenth+6 > sizeof(*ptr))
		{
			me->recvDataLenth =0;
			syslog(LOG_ERR,"dataProcessing data error");
			return -2;	
		}
	
		copyLenth = me->recvDataLenth-(ptr->datalenth+6);
		//crc校验
		ret = crc16Check(me->client_fd, me->recvDataBuff, ptr->datalenth+6);
		if(ret <0)
		{
			//删除错误数据并返回错误信息
			memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
			me->recvDataLenth =copyLenth;
			syslog(LOG_ERR,"dataProcessing crcCheck error");
			return -3;
		}
		//如果有监听设备数据转发到监听设备
		if(me->detect_fd !=-1)
			send(me->detect_fd, me->recvDataBuff, ptr->datalenth+6, 0);
		
		/************************数据处理待完善****************************/
		ret = storeDataToSQL(me, ptr->data, ptr->datalenth);
		if(ret <0)
		{
			//删除错误数据并返回错误信息
			memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
			me->recvDataLenth =copyLenth;
			syslog(LOG_ERR,"dataProcessing store data error");
			return -4;
		}
		/*****************************************************************/

		//将处理后的数据删除
		memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
		me->recvDataLenth =copyLenth;

		//上报时间更新
		ret = updateNodeTime(me);
			if(ret<0) return -5;
	}

	return 0;
}

/*
*	函数功能：		命令处理
*	函数参数	：	待处理节点指针
*	函数返回值：是否处理成功
*				成功：0
*				失败：<0
*/
static int cmdProcessing(PT_nodeList me)
{
	int ret;
	int copyLenth;
	struct data_st *ptr;

	if(me==NULL)
	{
		syslog(LOG_ERR,"cmdProcessing params error");
		err_message(me->client_fd, PARAMAS_ERR);
		return -1;
	}

	ptr = me->recvDataBuff;
	//满足一包数据长度处理数据
	if(me->recvDataLenth >= ptr->datalenth+6)
	{
		//判断数据长度是否超过定义的结构体长度
		if(ptr->datalenth+6 > sizeof(*ptr))
		{
			me->recvDataLenth =0;
			syslog(LOG_ERR,"cmdProcessing data error");
			return -2;	
		}
		
		copyLenth = me->recvDataLenth-(ptr->datalenth+6);
		//crc校验
		ret = crc16Check(me->client_fd, me->recvDataBuff, ptr->datalenth+6);
		if(ret <0)
		{
			//删除校验出错数据并返回错误信息
			memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
			me->recvDataLenth =copyLenth;
			syslog(LOG_ERR,"cmdProcessing crcCheck error");
			return -3;
		}
		//数据下发给监控的客户端
		if(me->detect_fd !=-1)
			send(me->detect_fd, me->recvDataBuff, ptr->datalenth+6, 0);

		//数据下发后将其删除
		memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
		me->recvDataLenth =copyLenth;

		//上报时间更新
		ret = updateNodeTime(me);
			if(ret<0) return -4;
	}

	return 0;
}

/*
*	函数功能：		数据查询处理
*	函数参数	：	待处理节点指针
*	函数返回值：是否处理成功
*				成功：0
*				失败：<0
*/
static int queryProcessing(PT_nodeList me)
{
	int ret;
	int copyLenth;
	struct data_st *ptr;

	if(me==NULL)
	{
		syslog(LOG_ERR,"queryProcessing params error");
		err_message(me->client_fd, PARAMAS_ERR);
		return -1;
	}

	ptr = me->recvDataBuff;
	//满足一包数据长度处理数据
	if(me->recvDataLenth >= ptr->datalenth+6)
	{
		//判断数据长度是否超过定义的结构体长度
		if(ptr->datalenth+6 > sizeof(*ptr))
		{
			me->recvDataLenth =0;
			syslog(LOG_ERR,"cmdProcessing data error");
			return -2;	
		}
		
		copyLenth = me->recvDataLenth-(ptr->datalenth+6);
		//crc校验
		ret = crc16Check(me->client_fd, me->recvDataBuff, ptr->datalenth+6);
		if(ret <0)
		{
			//删除校验出错数据并返回错误信息
			memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
			me->recvDataLenth =copyLenth;
			syslog(LOG_ERR,"cmdProcessing crcCheck error");
			return -3;
		}

		/************************数据处理待完善****************************/
		ret = queryDataFromSQL(me, ptr->data, ptr->datalenth);
		if(ret <0)
		{
			//删除错误数据并返回错误信息
			memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
			me->recvDataLenth =copyLenth;
			syslog(LOG_ERR,"dataProcessing store data error");
			return -4;
		}
		/*****************************************************************/
		
		//处理完后将其删除
		memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
		me->recvDataLenth =copyLenth;

		//上报时间更新
		ret = updateNodeTime(me);
			if(ret<0) return -4;
	}

	return 0;
}

/*
*	函数功能：		数据查询处理
*	函数参数	：	待处理节点指针
*	函数返回值：是否处理成功
*				成功：0
*				失败：<0
*/
static int heartBeatProcessing(PT_nodeList me)
{
	int ret;
	int copyLenth;
	struct data_st *ptr;

	if(me==NULL)
	{
		syslog(LOG_ERR,"queryProcessing params error");
		err_message(me->client_fd, PARAMAS_ERR);
		return -1;
	}

	ptr = me->recvDataBuff;
	//满足一包数据长度处理数据
	if(me->recvDataLenth >= ptr->datalenth+6)
	{
		//判断数据长度是否超过定义的结构体长度
		if(ptr->datalenth+6 > sizeof(*ptr))
		{
			me->recvDataLenth =0;
			syslog(LOG_ERR,"heartBeatProcessing data error");
			return -2;	
		}
	
		copyLenth = me->recvDataLenth-(ptr->datalenth+6);
		//crc校验
		ret = crc16Check(me->client_fd, me->recvDataBuff, ptr->datalenth+6);
		if(ret <0)
		{
			//删除错误数据返回错误信息
			memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
			me->recvDataLenth =copyLenth;
			syslog(LOG_ERR,"heartBeatProcessing crcCheck error");
			return -3;
		}
		//删除此包数据
		memcpy(me->recvDataBuff, me->recvDataBuff+ptr->datalenth+6, copyLenth);
		me->recvDataLenth =copyLenth;
		
		//上报时间更新
		ret = updateNodeTime(me);
			if(ret<0) return -4;
	}

	return 0;
}

/*
*	函数功能：		数据分析
*	函数参数	：	1、指定客户端
*				2、数据长度
*				3、数据缓存地址
*	函数返回值：是否分析成功
*				成功：0
*				失败：<0
*/
static int dataAnalysis(int clientfd, int lenth, void *buff)
{
	union packetData *data = buff;
	int ret,copyLenth;
	PT_nodeList me;

	if(data->type<=0 || data->type>=DATATYPEMAX || clientfd<0 || lenth<=0)
	{
		syslog(LOG_ERR,"Analysis params error");
		err_message(clientfd, PARAMAS_ERR);
		return -1;
	}

	//在nodeList中查找节点
	me = findNode_fd_unLock(clientfd);
	if(me ==NULL)
	{
		syslog(LOG_ERR,"Analysis don't find Node");
		err_message(clientfd, CLIENTID_ERR);
		return -2;
	}

	//判断节点是否为新加入节点
	if(me->recvDataBuff ==NULL)
	{
		ret = crc16Check(clientfd, buff,lenth);
		if(ret <0) return -3;

		//新加入节点修改节点信息
		switch(data->type)
		{
			case CLIENT_ID:
				ret = nodeList_editNode_unLock(me,data->client.id,NULL);
				if(ret <0)
				{
					syslog(LOG_ERR,"Analysis editNode clientid error");
					err_message(clientfd, CLIENTID_ERR);
					return -4;
				}
				break;
				
			case DETECT_ID:
				ret = nodeList_editNode_unLock(me,data->detect.id,data->detect.clientid);
				if(ret <0)
				{
					syslog(LOG_ERR,"Analysis editNode clientid error");
					err_message(clientfd, DETECTID_ERR);
					return -5;
				}
				break;
				
			case DATA:
			case CMD:
			case QUERY:
			case HEARTBEAT:
				break;
			
			default:
				syslog(LOG_ERR,"Analysis unkown data type");
				err_message(clientfd, ANALYSIS_ERR);
				break;
		}
	}
	else
	{
		if(data->type!=CLIENT_ID && data->type!=DETECT_ID)
		{
			//正常节点判断数据是否超过缓冲区大小
			if(me->recvDataLenth+lenth >=DATABUFFSZIE)
			{
				copyLenth = DATABUFFSZIE- me->recvDataLenth+lenth;
				syslog(LOG_ERR,"Analysis data too much");
				err_message(clientfd, DATA_ERR);
			}
			else
				copyLenth = lenth;

			//正常节点将数据放入节点数据缓存区
			memcpy(me->recvDataBuff+me->recvDataLenth, buff, copyLenth);
			me->recvDataLenth +=copyLenth;
		}

		//缓冲区数据分析
		switch(data->type)
		{
			case CLIENT_ID:
			case DETECT_ID:
				break;
			
			case DATA:
				ret = dataProcessing(me);
				if(ret<0) return -6;
				break;
			
			case CMD:
				ret = cmdProcessing(me);
				if(ret<0) return -7;
				break;
				
			case QUERY:
				ret = queryProcessing(me);
				if(ret<0) return -8;
				break;
				
			case HEARTBEAT:
				ret = heartBeatProcessing(me);
				if(ret<0) return -9;
				break;
				
			default:
				syslog(LOG_ERR,"Analysis unkown data type");
				err_message(clientfd, ANALYSIS_ERR);
				break;	
		}
	}

	return 0;
}

/*
*	函数功能：		epoll调用数据接收函数
*	函数参数	：	PT_threadFun结构体指针
*	函数返回值：是否处理成功
*				成功：0
*				失败：<0
*/
int func_handler(void *data)
{
	char buff[BUFFSIZE] ={0};
	int lenth,ret;
	PT_threadFun clientData = data;

	lenth = recv(clientData->clientfd,buff,BUFFSIZE,0);
	if(lenth <0)  //数据读取错误
	{
		err_message(clientData->clientfd, RECEV_ERR);
		pthread_mutex_lock(&clientData->threadPool->mutex);
		nodeList_delNode_unLock(clientData->clientfd);
		pthread_mutex_unlock(&clientData->threadPool->mutex);
		syslog(LOG_ERR,"recv error");
		return -1;
	}
	else if(lenth == 0)	//客户端退出
	{
		pthread_mutex_lock(&clientData->threadPool->mutex);
		nodeList_delNode_unLock(clientData->clientfd);
		pthread_mutex_unlock(&clientData->threadPool->mutex);
		syslog(LOG_ERR,"client exit");
	}
	else	//接收到数据
	{
		ret = dataAnalysis(clientData->clientfd,lenth,buff);
		if(ret <0)
		{
			syslog(LOG_ERR,"data analysis error");
			return -2;
		}
	}

	return 0;
}

